#ifndef AI_REFLEX_H
#define AI_REFLEX_H



#include "ai.h"



/** @brief The main algorithm class.
*
*   This algorithm is based on static analysis of game_state without any searching of state space. The whole %algorithm runs in three phases in function
*   reflex_algorithm::generate_commands(). Phase 1 and 3 generate commands to reflex_algorithm::move_commands list and phase 2 generates commands to
*   reflex_algorithm::fire_commands list:
*
*   - Phase 1: This phase checks game_state::dangerous_places and determines, if any players unit is in danger using
*              reflex_algorithm::check_dangerous_places( bool apply ) and finds safer place using
*              reflex_algorithm::find_safe_place( unit* u, game_state* state ). Safer plas is being found in square determined by units place
*              and the longest distance, that the unit could reach when the terrain is flat. It meand, that remaining time is divided by unit::cost_move
*              value. Safer place means, that less oponnents units can attack there. If there are two places, that have the same safety, the closer is choosen.
*              Found places are used only to determine time needed to get there and so the Phase 2 will run with time reduced by this estimation.
*
*   - Phase 2: That phase is offensive one. It is whole implemented in function reflex_algorithm::find_target_or_move( game_state* state ), that checks,
*              if any unit can attack using reflex_algorithm::can_anybody_attack( game_state* state ). It check for each unit the game_state::attackable_places
*              array. This phase is divided into 2 subphases. Subphase 1 is run when some unit can attack, subphase 2 when nobody can attack.
*      - Subphase 1: Here the reflex_algorithm::find_best_target( game_state* state ) function is executed and if finds best pair of unit and target. It is made
*                    using function reflex_algorithm::find_best_target_unit( unit* u, game_state* state ) executed for each player's unit. 
*      - Subphase 2: When no unit can attack opponent, some better plac is found using reflex_algorithm::find_better_place( game_state* state ), that executes
*                    function reflex_algorithm::find_better_place_unit( unit* u, game_state* state ), that finds place, that is closer to place, from where
*                    the unit can attack. The place is found uning game_state::range_places structure.
*                    The reflex_algorithm::find_better_place_unit( unit* u, game_state* state ) function looks to all four directions, if this place is closer
*                    to the place, from where the unit can attack and takes the plas, where the movement is the cheapest. If the place has in
*                    game_state::dangerous_places non zero value, the function doubles the cost of movement in order to be able to return from opponents
*                    sight. Together with phase 1, it gives us chance to get back to safe places. Every unit, that returns will be excluded for further movements
*                    except defensive ones. It is done with reflex_algorithm::returned_units. 
*
*   - Phase3: This phase is very similar to phase 1, but it doesn't only simulate the movements, but id really generates the move commands.
*
*   All phases run in cycles until they find some commands.
*
*   \image html ai_reflex.jpeg
*/
class reflex_algorithm: public algorithm
{

public:

	//! @brief Constructor only assignes the name
	reflex_algorithm()
	{
		name = "Reflex algorithm";
		state = 0;
	};
	~reflex_algorithm()
	{
		if ( state != 0 )
			delete state;
	};

	/** @brief	Registrating function (adds ai algorithm to map)
	*/
	static void register_me()
	{
		register_metpl< reflex_algorithm >();
	};

	/** @brief	Cloning function for init purposes
	*	@return	clone of the algorithm
	*/
	virtual algorithm* clone()
	{
		reflex_algorithm* cl = clonetpl< reflex_algorithm >();
		return cl;
	};

	/** @brief Function called at the beginning of buy
	*	@param gs current game state
	*/
	virtual void get_buy_commands( const game_state* gs );
	/** @brief Function called at the beginning of every turn
	*	@param gs current game state
	*/
	virtual void get_commands( const game_state* gs );


private:

	//! @brief generates all AI commands recousively until there are some new found
	void generate_commands();
	/** @brief Checks if there are any units in danger and adds appropriate commands to move_commands gueue
	*	@param apply if commands should be applied on main state
	*/
	void check_dangerous_places( bool apply );
	//! @brief Checks if there are any units to attack to and adds appropriate commands to fire_commands gueue
	void check_attackable_places();
	/**	@brief	Finds safe place for given unit
	*	@param	u unit, for which to find the safe place, constraint: u != 0
	*	@param	state game_state, where to find the safe place, constraint: state != 0
	*	@return	coordinates of the safe place
	*/
	pair< int, int > find_safe_place( unit* u, game_state* state );
	/** @brief Finds, if there is some attackable unit, if not, moves closer to any of the opponents units
	*	@param state game_state where to compute commands, , constraint: state != 0
	*/
	void find_target_or_move( game_state* state );
	/**	@brief	Finds the best attacking and attackable unit
	*	@param	state state where to find the pair, constraint: state != 0
	*	@return	unit number to attack with and coordinates where to attack
	*/
	pair< int, pair< int, int > > find_best_target( game_state* state );
	/**	@brief	Finds the best target for given unit
	*	@param	u unit, for which to find the target, constraint: u != 0
	*	@param	state game_state, where to find the target, constraint: state != 0
	*	@return	coordinates of the best target
	*/
	pair< int, int > find_best_target_unit( unit* u, game_state* state );
	/**	@brief	Checks if any unit can attack somebody
	*	@param	state game_state, where to find the targets, constraint: state != 0
	*	@return	True if there is at least one such an unit, false if not
	*/
	bool can_anybody_attack( game_state* state );
	/**	@brief Finds pair unit and place where to move
	*	gets unit, that is the closest to the oponnent and finds a place for it, that is even closer
	*	@param	state game_state where to find the pair, constraint: state != 0
	*	@return	unit number to move with and coordinates where to move
	*/
	pair< int, pair< int, int > > find_better_place( game_state* state );
	/**	@brief Finds better place for given unit
	*	finds the closest place, from where it can attack opponent and finds a place for it, that is closer, that it's position
	*	@param	u unit, for which to find the place, constraint: u != 0
	*	@param	state game_state, where to find the place, constraint: state != 0
	*	@return	coordinates of the better place and distance there
	*/
	pair< int, pair< int, int > > find_better_place_unit( unit* u, game_state* state );

	//! list of commands for moving
	list< string > move_commands;
	//! list of commands for attacking
	list< string > fire_commands;
	//! vector, where true is on place, where unit has returned from dangerou place
	vector< bool > returned_units;

	//! remaining time (for computing purposes)
	int rem_time;
	//! given state - never changed
	const game_state* original_state;
	//! given state
	game_state* state;

};



#endif